package com.dms.modules.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dms.modules.product.entity.Product;
import com.dms.modules.product.entity.ProductFavorite;
import com.dms.modules.product.entity.ProductRecommendationMetrics;
import com.dms.modules.product.mapper.ProductMapper;
import com.dms.modules.product.mapper.ProductFavoriteMapper;
import com.dms.modules.product.mapper.ProductRecommendationMetricsMapper;
import com.dms.modules.product.service.ProductAnalyticsService;
import com.dms.modules.order.entity.Order;
import com.dms.modules.order.mapper.OrderMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 商品分析服务实现类
 */
@Slf4j
@Service
public class ProductAnalyticsServiceImpl implements ProductAnalyticsService {

    private static final String ANALYTICS_CACHE_KEY = "product:analytics:";
    private static final String CONVERSION_CACHE_KEY = "product:conversion:";
    private static final String HOT_RANKING_CACHE_KEY = "product:hot:ranking:";
    private static final String SALES_TREND_CACHE_KEY = "product:sales:trend:";
    private static final String USER_BEHAVIOR_CACHE_KEY = "product:user:behavior:";
    private static final String CATEGORY_ANALYTICS_CACHE_KEY = "product:category:analytics:";
    private static final String SEARCH_HOT_CACHE_KEY = "product:search:hot:";
    private static final String RECOMMENDATION_EFFECT_CACHE_KEY = "product:recommendation:effect:";
    
    private static final long CACHE_EXPIRE_HOURS = 24;
    
    @Autowired
    private ProductMapper productMapper;
    
    @Autowired
    private ProductFavoriteMapper favoriteMapper;
    
    @Autowired
    private ProductRecommendationMetricsMapper metricsMapper;
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public Map<String, Object> getProductAnalytics(Long productId) {
        // 如果productId为null，返回所有商品的统计数据
        if (productId == null) {
            return getOverallProductAnalytics();
        }
        
        String cacheKey = ANALYTICS_CACHE_KEY + productId;
        Map<String, Object> cachedData = (Map<String, Object>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedData != null) {
            return cachedData;
        }
        
        Map<String, Object> analytics = new HashMap<>();
        
        try {
            // 获取商品基本信息
            Product product = productMapper.selectById(productId);
            if (product == null) {
                return analytics;
            }
            
            // 获取收藏数
            Long favoriteCount = getFavoriteCount(productId);
            
            // 获取推荐指标数据
            List<ProductRecommendationMetrics> metrics = getProductMetrics(productId);
            
            // 计算总点击数和总浏览量
            int totalClicks = metrics.stream().mapToInt(ProductRecommendationMetrics::getClickCount).sum();
            int totalViews = metrics.stream().mapToInt(ProductRecommendationMetrics::getViewCount).sum();
            
            // 获取购买数
            Long purchaseCount = getPurchaseCount(productId);
            
            // 组装分析数据
            analytics.put("productId", productId);
            analytics.put("viewCount", product.getViewCount());
            analytics.put("favoriteCount", favoriteCount);
            analytics.put("clickCount", totalClicks);
            analytics.put("purchaseCount", purchaseCount);
            
            // 计算转化率
            if (totalViews > 0) {
                BigDecimal conversionRate = calculateConversionRate(purchaseCount, totalViews);
                analytics.put("conversionRate", conversionRate);
            } else {
                analytics.put("conversionRate", BigDecimal.ZERO);
            }
            
            // 缓存数据
            redisTemplate.opsForValue().set(cacheKey, analytics, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
            
        } catch (Exception e) {
            log.error("Failed to get product analytics for productId: {}", productId, e);
        }
        
        return analytics;
    }

    /**
     * 获取所有商品的总体统计数据
     */
    private Map<String, Object> getOverallProductAnalytics() {
        String cacheKey = ANALYTICS_CACHE_KEY + "overall";
        Map<String, Object> cachedData = (Map<String, Object>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedData != null) {
            return cachedData;
        }

        Map<String, Object> analytics = new HashMap<>();
        
        try {
            // 获取商品总数
            Long totalProducts = productMapper.selectCount(new LambdaQueryWrapper<Product>()
                .eq(Product::getDeleted, 0));
            analytics.put("totalProducts", totalProducts);

            // 获取在售商品数
            Long activeProducts = productMapper.selectCount(new LambdaQueryWrapper<Product>()
                .eq(Product::getStatus, 1)
                .eq(Product::getDeleted, 0));
            analytics.put("activeProducts", activeProducts);

            // 获取总浏览量
            Integer totalViews = productMapper.selectList(new LambdaQueryWrapper<Product>()
                .eq(Product::getDeleted, 0))
                .stream()
                .mapToInt(Product::getViewCount)
                .sum();
            analytics.put("totalViews", totalViews);

            // 获取总销量和销售额
            List<Map<String, Object>> salesData = orderMapper.selectProductSalesAnalytics();
            if (!salesData.isEmpty()) {
                Map<String, Object> sales = salesData.get(0);
                analytics.put("totalSales", sales.get("totalSales"));
                analytics.put("totalRevenue", sales.get("totalRevenue"));
            }

            // 计算整体转化率
            if (totalViews > 0 && salesData != null && !salesData.isEmpty()) {
                Long totalSales = ((Number) salesData.get(0).get("totalSales")).longValue();
                BigDecimal conversionRate = calculateConversionRate(totalSales, totalViews);
                analytics.put("conversionRate", conversionRate);
            } else {
                analytics.put("conversionRate", BigDecimal.ZERO);
            }

            // 缓存数据
            redisTemplate.opsForValue().set(cacheKey, analytics, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
            
        } catch (Exception e) {
            log.error("Failed to get overall product analytics", e);
        }
        
        return analytics;
    }

    @Override
    public Map<String, Object> getProductConversionRate(Long productId) {
        String cacheKey = CONVERSION_CACHE_KEY + productId;
        Map<String, Object> cachedData = (Map<String, Object>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedData != null) {
            return cachedData;
        }
        
        Map<String, Object> conversionData = new HashMap<>();
        
        try {
            // 获取推荐指标数据
            List<ProductRecommendationMetrics> metrics = getProductMetrics(productId);
            
            // 计算总点击数和总浏览量
            int totalClicks = metrics.stream().mapToInt(ProductRecommendationMetrics::getClickCount).sum();
            int totalViews = metrics.stream().mapToInt(ProductRecommendationMetrics::getViewCount).sum();
            
            // 获取购买数
            Long purchaseCount = getPurchaseCount(productId);
            
            // 计算各阶段转化率
            if (totalViews > 0) {
                BigDecimal viewToClickRate = calculateConversionRate(totalClicks, totalViews);
                conversionData.put("viewToClickRate", viewToClickRate);
                
                BigDecimal viewToPurchaseRate = calculateConversionRate(purchaseCount, totalViews);
                conversionData.put("viewToPurchaseRate", viewToPurchaseRate);
            } else {
                conversionData.put("viewToClickRate", BigDecimal.ZERO);
                conversionData.put("viewToPurchaseRate", BigDecimal.ZERO);
            }
            
            // 缓存数据
            redisTemplate.opsForValue().set(cacheKey, conversionData, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
            
        } catch (Exception e) {
            log.error("Failed to get product conversion rate for productId: {}", productId, e);
        }
        
        return conversionData;
    }

    @Override
    public Map<String, Object> getHotProductsRanking(Integer limit) {
        String cacheKey = HOT_RANKING_CACHE_KEY + limit;
        Map<String, Object> cachedData = (Map<String, Object>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedData != null) {
            return cachedData;
        }
        
        Map<String, Object> rankingData = new HashMap<>();
        
        try {
            // 获取热门商品
            List<Product> hotProducts = productMapper.selectList(
                new LambdaQueryWrapper<Product>()
                    .eq(Product::getStatus, 1)
                    .orderByDesc(Product::getViewCount)
                    .last("LIMIT " + limit)
            );
            
            // 获取每个商品的收藏数和购买数
            List<Map<String, Object>> productRankings = hotProducts.stream().map(product -> {
                Map<String, Object> productData = new HashMap<>();
                productData.put("productId", product.getId());
                productData.put("productName", product.getName());
                productData.put("viewCount", product.getViewCount());
                
                // 获取收藏数
                Long favoriteCount = getFavoriteCount(product.getId());
                productData.put("favoriteCount", favoriteCount);
                
                // 获取购买数
                Long purchaseCount = getPurchaseCount(product.getId());
                productData.put("purchaseCount", purchaseCount);
                
                return productData;
            }).collect(Collectors.toList());
            
            rankingData.put("products", productRankings);
            
            // 缓存数据
            redisTemplate.opsForValue().set(cacheKey, rankingData, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
            
        } catch (Exception e) {
            log.error("Failed to get hot products ranking for limit: {}", limit, e);
        }
        
        return rankingData;
    }
    
    @Override
    public Map<String, Object> getProductSalesTrend(Long productId, Integer days) {
        String cacheKey = SALES_TREND_CACHE_KEY + productId + ":" + days;
        Map<String, Object> cachedData = (Map<String, Object>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedData != null) {
            return cachedData;
        }
        
        Map<String, Object> trendData = new HashMap<>();
        
        try {
            LocalDateTime endDate = LocalDateTime.now();
            LocalDateTime startDate = endDate.minus(days, ChronoUnit.DAYS);
            
            // 获取销售数据
            List<Map<String, Object>> salesData = orderMapper.selectProductSalesTrend(
                productId, startDate, endDate);
            
            trendData.put("productId", productId);
            trendData.put("salesData", salesData);
            
            // 缓存数据
            redisTemplate.opsForValue().set(cacheKey, trendData, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
            
        } catch (Exception e) {
            log.error("Failed to get product sales trend for productId: {} and days: {}", productId, days, e);
        }
        
        return trendData;
    }
    
    @Override
    public Map<String, Object> getProductUserBehavior(Long productId) {
        String cacheKey = USER_BEHAVIOR_CACHE_KEY + productId;
        Map<String, Object> cachedData = (Map<String, Object>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedData != null) {
            return cachedData;
        }
        
        Map<String, Object> behaviorData = new HashMap<>();
        
        try {
            // 获取用户行为数据
            List<Map<String, Object>> userBehavior = orderMapper.selectProductUserBehavior(productId);
            
            behaviorData.put("productId", productId);
            behaviorData.put("userBehavior", userBehavior);
            
            // 缓存数据
            redisTemplate.opsForValue().set(cacheKey, behaviorData, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
            
        } catch (Exception e) {
            log.error("Failed to get product user behavior for productId: {}", productId, e);
        }
        
        return behaviorData;
    }
    
    @Override
    public Map<String, Object> getCategoryAnalytics(Long categoryId) {
        String cacheKey = CATEGORY_ANALYTICS_CACHE_KEY + categoryId;
        Map<String, Object> cachedData = (Map<String, Object>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedData != null) {
            return cachedData;
        }
        
        Map<String, Object> categoryData = new HashMap<>();
        
        try {
            // 获取分类分析数据
            List<Map<String, Object>> categoryAnalytics = orderMapper.selectCategoryAnalytics(categoryId);
            
            categoryData.put("categoryId", categoryId);
            categoryData.put("analytics", categoryAnalytics);
            
            // 缓存数据
            redisTemplate.opsForValue().set(cacheKey, categoryData, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
            
        } catch (Exception e) {
            log.error("Failed to get category analytics for categoryId: {}", categoryId, e);
        }
        
        return categoryData;
    }
    
    @Override
    public Map<String, Object> getSearchHotRanking(Integer limit) {
        String cacheKey = SEARCH_HOT_CACHE_KEY + limit;
        Map<String, Object> cachedData = (Map<String, Object>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedData != null) {
            return cachedData;
        }
        
        Map<String, Object> rankingData = new HashMap<>();
        
        try {
            // 获取搜索热度排行
            List<Map<String, Object>> searchRanking = orderMapper.selectSearchHotRanking(limit);
            
            rankingData.put("limit", limit);
            rankingData.put("ranking", searchRanking);
            
            // 缓存数据
            redisTemplate.opsForValue().set(cacheKey, rankingData, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
            
        } catch (Exception e) {
            log.error("Failed to get search hot ranking for limit: {}", limit, e);
        }
        
        return rankingData;
    }
    
    @Override
    public Map<String, Object> getRecommendationEffectiveness(Long productId) {
        String cacheKey = RECOMMENDATION_EFFECT_CACHE_KEY + productId;
        Map<String, Object> cachedData = (Map<String, Object>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedData != null) {
            return cachedData;
        }
        
        Map<String, Object> effectivenessData = new HashMap<>();
        
        try {
            // 获取推荐效果数据
            List<ProductRecommendationMetrics> metrics = getProductMetrics(productId);
            
            // 计算推荐效果指标
            int totalRecommendations = metrics.size();
            int totalClicks = metrics.stream().mapToInt(ProductRecommendationMetrics::getClickCount).sum();
            int totalViews = metrics.stream().mapToInt(ProductRecommendationMetrics::getViewCount).sum();
            
            effectivenessData.put("productId", productId);
            effectivenessData.put("totalRecommendations", totalRecommendations);
            effectivenessData.put("totalClicks", totalClicks);
            effectivenessData.put("totalViews", totalViews);
            
            if (totalViews > 0) {
                BigDecimal ctr = calculateConversionRate(totalClicks, totalViews);
                effectivenessData.put("ctr", ctr);
            } else {
                effectivenessData.put("ctr", BigDecimal.ZERO);
            }
            
            // 缓存数据
            redisTemplate.opsForValue().set(cacheKey, effectivenessData, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
            
        } catch (Exception e) {
            log.error("Failed to get recommendation effectiveness for productId: {}", productId, e);
        }
        
        return effectivenessData;
    }
    
    // 私有辅助方法
    
    private Long getFavoriteCount(Long productId) {
        return favoriteMapper.selectCount(
            new LambdaQueryWrapper<ProductFavorite>()
                .eq(ProductFavorite::getProductId, productId)
        );
    }
    
    private List<ProductRecommendationMetrics> getProductMetrics(Long productId) {
        return metricsMapper.selectList(
            new LambdaQueryWrapper<ProductRecommendationMetrics>()
                .like(ProductRecommendationMetrics::getRecommendedProductIds, productId.toString())
        );
    }
    
    private Long getPurchaseCount(Long productId) {
        return orderMapper.selectCount(
            new LambdaQueryWrapper<Order>()
                .inSql(Order::getId, 
                    "SELECT order_id FROM order_item WHERE product_id = " + productId)
                .eq(Order::getStatus, 1)
        );
    }
    
    private BigDecimal calculateConversionRate(long numerator, long denominator) {
        return new BigDecimal(numerator)
            .divide(new BigDecimal(denominator), 4, RoundingMode.HALF_UP)
            .multiply(new BigDecimal(100));
    }
} 